package com.xiaoshuidi.cloud.module.contract.job;

import com.alibaba.fastjson.JSONObject;
import com.xiaoshuidi.cloud.framework.tenant.core.aop.TenantIgnore;
import com.xiaoshuidi.cloud.framework.tenant.core.job.TenantJob;
import com.xiaoshuidi.cloud.module.contract.controller.admin.contract.vo.ContractConfigReqVO;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.contract.ContractRoomDO;
import com.xiaoshuidi.cloud.module.contract.dal.mysql.contract.ContractRoomMapper;
import com.xiaoshuidi.cloud.module.contract.enums.contract.*;
import com.xiaoshuidi.cloud.module.contract.service.contract.ContractConfigService;
import com.xiaoshuidi.cloud.module.contract.service.contract.ContractRoomService;
import com.xiaoshuidi.cloud.module.contract.service.contract.dto.ContractRoomQueryParamDTO;
import com.xiaoshuidi.cloud.module.iot.common.ResultModel;
import com.xiaoshuidi.cloud.module.rooms.api.roomstate.RoomStateRecordApi;
import com.xiaoshuidi.cloud.module.rooms.api.roomstate.dto.UpdateRoomStateReqDTO;
import com.xiaoshuidi.cloud.module.rooms.api.sdiot.IotRoomDeviceApi;
import com.xiaoshuidi.cloud.module.rooms.enums.RoomContractStatusEnum;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

import static com.xiaoshuidi.cloud.module.contract.enums.ApiConstants.ZERO;

@Slf4j
@Component
@TenantJob
@RefreshScope
public class RoomContractJob {

//    @Value("${contract.job.expire-times}")
    private Long EXPIRE_TIMES=2L;
    @Resource
    private ContractRoomService contractRoomService;
    @Resource
    private ContractConfigService contractConfigService;
    @Resource
    private IotRoomDeviceApi iotRoomDeviceApi;
    @Resource
    private ContractRoomMapper contractRoomMapper;
    @Resource
    private RoomStateRecordApi roomStateRecordApi;


    /**
     * 已生效合同自动失效
     * 已生效新签续租合同不支付自动失效
     */
    @XxlJob("change-active-unpaid-contract-status")
    public void changeActiveUnPaidContractStatus() {
        log.info("已生效新签续租合同不支付自动失效 - 执行开始");
        LocalDateTime now = LocalDateTime.now();
        if (Objects.isNull(EXPIRE_TIMES)){
            EXPIRE_TIMES = 2L;
        }
        // 失效时间
        LocalDateTime expireTime = now.plusHours(-1 * EXPIRE_TIMES);

        // 查询合同数据 1合同状态-已生效 2变更生效时间-小于等于限制时间 3合同节点-新签续租 4个人合同
        ContractRoomQueryParamDTO param = new ContractRoomQueryParamDTO();
        param.setContractStatusList(Arrays.asList(ContractStatusEnum.ACTIVE.getCode(), ContractStatusEnum.CHECK_IN.getCode()));
        param.setLeChangeEffectiveTime(expireTime);
        List<String> nodeList = Arrays.asList(ContractNodeEnum.NEW.getCode(), ContractNodeEnum.RENEWAL.getCode());
        param.setContractNodeList(nodeList);
        param.setCustomerType(CustomerTypeEnum.PERSONAL.getCode());
        List<ContractRoomDO> unpaidContractList = contractRoomService.getFirstOrderUnpaidContractList(param);
        log.info("查询到的未支付首期账单的合同：{}", CollectionUtils.isNotEmpty(unpaidContractList)?JSONObject.toJSONString(unpaidContractList):"null");
        if (CollectionUtils.isNotEmpty(unpaidContractList)){
            // 修改合同状态为已失效
            contractRoomService.updateBatchExpireAndChangeRoomStatus(unpaidContractList);
            // 续租合同 回滚原合同状态
            contractRoomService.rollbackOriginContract(unpaidContractList);
        }
        log.info("已生效新签续租合同不支付自动失效 - 执行结束");
    }


    /**
     * 合同发起签约后自动失效
     * 发起签约后配置时间内乙方未签约合同失效
     */
    @XxlJob("initiate-sign-auto-expire")
    public void initiateSignAutoExpire() {
        log.info("发起签约后自动失效 - 执行开始");
        LocalDateTime now = LocalDateTime.now();
        ContractConfigReqVO contractConfigDO = contractConfigService.getContractConfig();
        if (Objects.isNull(contractConfigDO)){
            return;
        }
        Integer contractSignedAging = contractConfigDO.getContractSignedAging();
        if (!contractConfigDO.getContractSignedAgingStatus() || ZERO.intValue() >= contractSignedAging){
            return;
        }
        LocalDateTime dateTime = now.plusHours(-1 * contractSignedAging);
        // 查询合同 1租户 2甲方签约时间小于等于限制时间 3在线签约状态-待乙方签约 4合同状态-待签约 5个人合同 6电子合同 7新签续租
        ContractRoomQueryParamDTO param = new ContractRoomQueryParamDTO();
        param.setLeLessorSignTime(dateTime);
        param.setSignStatus(ContractSignStatusEnum.SIGNED_PARTY_B.getCode());
        param.setContractStatus(ContractStatusEnum.NO_SIGNED.getCode());
        param.setCustomerType(CustomerTypeEnum.PERSONAL.getCode());
        param.setContractSort(ContractTypeEnum.ELECTRONIC.getCode());
        List<String> nodeList = Arrays.asList(ContractNodeEnum.NEW.getCode(), ContractNodeEnum.RENEWAL.getCode());
        param.setContractNodeList(nodeList);
        List<ContractRoomDO> roomContractList = contractRoomService.getRoomContractListByParam(param);
        if (CollectionUtils.isNotEmpty(roomContractList)){
            // 修改合同状态为已失效
            contractRoomService.updateBatchExpireAndChangeRoomStatus(roomContractList);
            // 续租合同 回滚原合同状态
            contractRoomService.rollbackOriginContract(roomContractList);
        }
        log.info("发起签约后自动失效 - 执行结束");
    }

    /**
     * 续租换房原合同自动结束
     * 续租换房合同变为当前合同，原合同变为历史合同
     */
    @XxlJob("renewal-exchange-auto-effect")
    public void renewalExchangeAutoEffect() {
        log.info("续租换房原合同自动失效 - 执行开始");
        String jobParam = XxlJobHelper.getJobParam();
        LocalDate date = LocalDate.now();
        if (StringUtils.isNotBlank(jobParam)){
            // 传参若是未来日期，默认为当前日期
            try {
                LocalDate paramDate = LocalDate.parse(jobParam);
                if (paramDate.isBefore(date)){
                    date = paramDate;
                }
            } catch (Exception e) {
                log.error("续租换房原合同自动失效，参数转换异常", e);
            }
        }
        LocalDate finalDate = date;
        // 查询合同 1合同节点-续租、换房 2合同状态-已生效、入住 3合同开始时间-限制时间
        ContractRoomQueryParamDTO param = new ContractRoomQueryParamDTO();
        List<String> nodeList = Arrays.asList(ContractNodeEnum.RENEWAL.getCode(), ContractNodeEnum.EXCHANGE.getCode());
        param.setContractNodeList(nodeList);
        List<String> statusList = Arrays.asList(ContractStatusEnum.ACTIVE.getCode(), ContractStatusEnum.CHECK_IN.getCode());
        param.setContractStatusList(statusList);
        param.setStartTime(finalDate);
        List<ContractRoomDO> roomContractList = contractRoomService.getRoomContractListByParam(param);
        if (CollectionUtils.isNotEmpty(roomContractList)){
            for (ContractRoomDO contractRoomDO : roomContractList) {
                // 处理合同信息
                contractRoomService.dealAutoEffect(contractRoomDO,date);
            }
        }
        log.info("续租换房原合同自动失效 - 执行结束");
    }

    @XxlJob("add-member")
    public void member() {
        log.info("添加主租人开始");
        contractRoomService.member();
        log.info("添加主租人结束");
    }


    /**
     * 合同逾期处理  断水电
     */
    @XxlJob("contract-overdue-deal")
    public void contractOverdueDeal() {
        log.info("合同逾期处理 - 执行开始");
        LocalDate date = LocalDate.now();
        // 查询逾期合同
        // 查询合同 1合同状态-已生效、入住 2合同结束时间-限制时间
        ContractRoomQueryParamDTO param = new ContractRoomQueryParamDTO();
        List<String> statusList = Arrays.asList(ContractStatusEnum.ACTIVE.getCode(), ContractStatusEnum.CHECK_IN.getCode());
        param.setContractStatusList(statusList);
        param.setLtEndTime(date);
        List<ContractRoomDO> roomContractList = contractRoomService.getRoomContractListByParam(param);
        // 调用断水电API接口
        if (CollectionUtils.isNotEmpty(roomContractList)){
            for (ContractRoomDO contractRoomDO : roomContractList) {
                log.info("合同逾期处理，逾期合同：{}", JSONObject.toJSONString(contractRoomDO));
                try {
                    ResultModel<Boolean> booleanResultModel = iotRoomDeviceApi.setWaterMeterAndAmmeterSwitchOff(contractRoomDO.getRoomId());
                    log.info("合同逾期处理，断水断电响应结果：{}", booleanResultModel.getData());
                } catch (Exception e) {
                    log.error("合同逾期处理，断水断电异常：",e);
                }
            }
        }
    }

    /**
     * 账单逾期处理  断水电
     */
    @XxlJob("rent-order-overdue-deal")
    public void rentOrderOverdueDeal() {
        // 查询逾期账单对应的合同
        List<ContractRoomDO> orderOverdueContractList = contractRoomMapper.getOrderOverdueContractList();
        // 调用断水电API接口
        if (CollectionUtils.isNotEmpty(orderOverdueContractList)){
            for (ContractRoomDO contractRoomDO : orderOverdueContractList) {
                log.info("账单逾期处理，逾期合同：{}", JSONObject.toJSONString(contractRoomDO));
                try {
                    ResultModel<Boolean> booleanResultModel = iotRoomDeviceApi.setWaterMeterAndAmmeterSwitchOff(contractRoomDO.getRoomId());
                    log.info("账单逾期处理，断水断电响应结果：{}", booleanResultModel.getData());
                } catch (Exception e) {
                    log.error("账单逾期处理，断水断电异常：",e);
                }
            }
        }
    }

    @XxlJob("contract-room-overdue")
    @TenantIgnore
    public void overdue(){
        List<ContractRoomDO> contractRoomDOS = contractRoomService.selectOverdue();
        List<UpdateRoomStateReqDTO> list = new ArrayList<>();
        for (ContractRoomDO contractRoomDO : contractRoomDOS) {
            UpdateRoomStateReqDTO updateRoomStateReqDTO = new UpdateRoomStateReqDTO();
            Long roomId = contractRoomDO.getRoomId();
            updateRoomStateReqDTO.setRoomHouseId(roomId);
            updateRoomStateReqDTO.setRoomContractStatusEnum(RoomContractStatusEnum.OVERDUE);
            list.add(updateRoomStateReqDTO);
        }
        log.info("生效或者入住状态中已过期合同：{}",JSONObject.toJSONString(list));
        roomStateRecordApi.updateRoomStateByContract(list);

    }

}
